home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / render.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  16KB  |  822 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    render -
  19.  *        Help use the graphics library to generate high resolution
  20.  *    rendered images.
  21.  *
  22.  *                Paul Haeberli - 1988
  23.  */
  24. #include "gl.h"
  25. #include "glmode.h"
  26. #include "values.h"
  27. #include "math.h"
  28. #include "image.h"
  29. #include "vect.h"
  30. #include "izoom.h"
  31.  
  32. static setvp();
  33. static zoomadd();
  34. static makename();
  35. static makeframe();
  36.  
  37. static int orthomode = 0;
  38. static float rl = -0.2;
  39. static float rr =  0.2;
  40. static float rb = -0.2;
  41. static float rt =  0.2;
  42. static float rnear = 1.0;
  43. static float rfar = 100.0;
  44. static float raspect = 1.0;
  45. static float rfocus = 5.0;
  46. static float raperture = 1.0;
  47. static float rpixeldiameter = 1.0;
  48. static float ox1, ox2, oy1, oy2, oz1, oz2;
  49. static int vpxsize, vpysize;
  50.  
  51. /* 
  52.  *     general rendering stuff follows 
  53.  *
  54.  *
  55.  */
  56. renderperspective(fov,aspect,near,far)
  57. int fov;
  58. float aspect, near, far;
  59. {
  60.     renderfperspective(fov/10.0,aspect,near,far);
  61. }
  62.  
  63. renderfperspective(fov,aspect,near,far)
  64. float fov;
  65. float aspect, near, far;
  66. {
  67.  
  68.     float tanval;
  69.  
  70.     tanval = near*tan(fov*M_PI/360.0);
  71.     renderwindow(-tanval*aspect,tanval*aspect,-tanval,tanval,near,far);
  72. }
  73.  
  74. renderwindow(l,r,b,t,near,far)
  75. float l,r,b,t,near,far;
  76. {
  77.     rl = l;
  78.     rr = r;
  79.     rb = b;
  80.     rt = t;
  81.     rnear = near;
  82.     rfar = far;
  83.     raspect = (r-l)/(t-b);
  84.     orthomode = 0;
  85.     restorewindow();
  86. }
  87.  
  88. getrenderwindow(l,r,b,t,near,far)
  89. float *l,*r,*b,*t,*near,*far;
  90. {
  91.     *l = rl;
  92.     *r = rr;
  93.     *b = rb;
  94.     *t = rt;
  95.     *near = rnear;
  96.     *far = rfar;
  97. }
  98.  
  99. renderortho(x1,x2,y1,y2,z1,z2)
  100. float x1,x2,y1,y2,z1,z2;
  101. {
  102.     ortho(x1,x2,y1,y2,z1,z2);
  103.     ox1 = x1;
  104.     ox2 = x2;
  105.     oy1 = y1;
  106.     oy2 = y2;
  107.     oz1 = z1;
  108.     oz2 = z2;
  109.     orthomode = 1;
  110. }
  111.  
  112. set35mmlens(focallength)
  113. float focallength;
  114. {
  115.     float dx, dy;
  116.  
  117.     dx = 18.0*(rnear/focallength);
  118.     dy = 12.0*(rnear/focallength);
  119.     renderwindow(-dx,dx,-dy,dy,rnear,rfar);
  120. }
  121.  
  122. setzclip(near,far)
  123. float near, far;
  124. {
  125.     rnear = near;
  126.     rfar = far;
  127.     restorewindow();
  128. }
  129.  
  130. setfocus(focus)
  131. float focus;
  132. {
  133.     rfocus = focus;
  134. }
  135.  
  136. setaperture(aper)
  137. float aper;
  138. {
  139.     raperture = aper;
  140. }
  141.  
  142. setpixeldiameter(d)
  143. float d;
  144. {
  145.     rpixeldiameter = d;
  146. }
  147.  
  148. setlensangle(angle)
  149. float angle;
  150. {
  151.     renderfperspective(angle,raspect,rnear,rfar);
  152. }
  153.  
  154. static float wpixdx, wpixdy;
  155. static float weyedx, weyedy;
  156. static float wfocus;
  157.  
  158. accset(pixdx,pixdy,eyedx,eyedy)
  159. float pixdx,pixdy,eyedx,eyedy;
  160. {
  161.     wpixdx = pixdx*rpixeldiameter; 
  162.     wpixdy = pixdy*rpixeldiameter; 
  163.     weyedx = eyedx*raperture; 
  164.     weyedy = eyedy*raperture; 
  165.     restorewindow();
  166. }
  167.  
  168. restorewindow()
  169. {
  170.     accwindow(rl,rr,rb,rt,rnear,rfar,wpixdx,wpixdy,weyedx,weyedy,rfocus);
  171. }
  172.  
  173. /*
  174.  *    accwindow -
  175.  *        Just like the window command, but lets you do
  176.  *    sub-pixel positioning, depth of field, and stereo,
  177.  *
  178.  *            Paul Haeberli - 1989
  179.  *
  180.  */
  181. accwindow(l,r,b,t,near,far,pixdx,pixdy,eyedx,eyedy,focus)
  182. float l, r, b, t, near, far;
  183. float pixdx, pixdy, eyedx, eyedy, focus;
  184. {
  185.     short vx1, vx2, vy1, vy2;
  186.     float xwsize, ywsize; 
  187.     float dx, dy;
  188.     int xpixels, ypixels;
  189.  
  190.     if(focus<0.0)
  191.     focus = -focus;
  192.     getviewport(&vx1,&vx2,&vy1,&vy2);
  193.     xpixels = vx2-vx1+1;
  194.     ypixels = vy2-vy1+1;
  195.     xwsize = r-l;
  196.     ywsize = t-b;
  197.     dx = -(pixdx*xwsize/xpixels+eyedx*near/focus);
  198.     dy = -(pixdy*ywsize/ypixels+eyedy*near/focus);
  199.     mmode(MPROJECTION);
  200.     window(l+dx,r+dx,b+dy,t+dy,near,far);
  201.     translate(-eyedx,-eyedy,0.0);
  202.     mmode(MVIEWING);
  203. }
  204.  
  205. accortho()
  206. {
  207.     fprintf(stderr,"accortho: not implemented\n");
  208. }
  209.  
  210. vpsize(xsize,ysize)
  211. int xsize, ysize;
  212. {
  213.     vpxsize = xsize;
  214.     vpysize = ysize;
  215. }
  216.  
  217. getvpsize(xsize,ysize)
  218. int *xsize, *ysize;
  219. {
  220.     short vx1, vx2, vy1, vy2;
  221.  
  222.     getviewport(&vx1,&vx2,&vy1,&vy2);
  223.     *xsize = vx2-vx1+1;
  224.     *ysize = vy2-vy1+1;
  225. }
  226.  
  227. clipvol(x,y,z,p)
  228. int x, y, z;
  229. vect *p;
  230. {
  231.     float zp;
  232.     long near, far;
  233.  
  234.     getzviewport(&near,&far);
  235.     p->x = 2.0*(x+0.5)/vpxsize - 1.0;
  236.     p->y = 2.0*(y+0.5)/vpysize - 1.0;
  237.     p->z = 2.0*((float)(z-near))/(far-near) - 1.0;
  238. }
  239.  
  240.  
  241. /*
  242.  *    Various render drawing functions
  243.  *
  244.  *
  245.  */
  246. rendertoscreen(drawfunc)
  247. int (*drawfunc)();
  248. {
  249.     mmode(MPROJECTION);
  250.     if(orthomode)
  251.     ortho(ox1,ox2,oy1,oy2,oz1,oz2);
  252.     else
  253.     window(rl,rr,rb,rt,rnear,rfar);
  254.     mmode(MVIEWING);
  255.     pushmatrix();
  256.     (drawfunc)();
  257.     popmatrix();
  258. }
  259.  
  260. renderstereo(drawfunc)
  261. int (*drawfunc)();
  262. {
  263. }
  264.  
  265. rendersubpix(drawfunc,xoffset,yoffset)
  266. int (*drawfunc)();
  267. float xoffset, yoffset;
  268. {
  269.     mmode(MPROJECTION);
  270.     if(orthomode) 
  271.     accortho(ox1,ox2,oy1,oy2,oz1,oz2,xoffset,yoffset,0.0,0.0,1.0);
  272.     else 
  273.     accset(xoffset,yoffset,0.0,0.0);
  274.     mmode(MVIEWING);
  275.     pushmatrix();
  276.     (drawfunc)();
  277.     popmatrix();
  278. }
  279.  
  280. shiftrender(drawfunc,xshift,yshift)
  281. int (*drawfunc)();
  282. float xshift, yshift;
  283. {
  284.     if(orthomode) {
  285.     fprintf(stderr,"shift render: huh?\n");
  286.     exit(1);
  287.     } else {
  288.     accset(0.0,0.0,xshift,yshift);
  289.     }
  290.     pushmatrix();
  291.     (drawfunc)();
  292.     popmatrix();
  293. }
  294.  
  295. subshiftrender(drawfunc,xsub,ysub,xshift,yshift)
  296. int (*drawfunc)();
  297. float xsub, ysub, xshift, yshift;
  298. {
  299.     mmode(MPROJECTION);
  300.     if(orthomode) {
  301.     fprintf(stderr,"shift render: huh?\n");
  302.     exit(1);
  303.     } else {
  304.     accset(xsub,ysub,xshift,yshift);
  305.     }
  306.     mmode(MVIEWING);
  307.     pushmatrix();
  308.     (drawfunc)();
  309.     popmatrix();
  310. }
  311.  
  312. rendertofile(drawfunc,outname,xsize,ysize)
  313. int (*drawfunc)();
  314. char *outname;
  315. int xsize, ysize;
  316. {
  317.     char filename[40];
  318.     char assemblecmd[4069];
  319.     char removecmd[4069];
  320.     char syscmd[4069];
  321.     long xdraw, ydraw;
  322.     int x, y, nx, ny;
  323.     int fno;
  324.  
  325.     getsize(&xdraw,&ydraw);
  326.     reshapeviewport();
  327.     if(xsize<=xdraw && ysize<=ydraw) {
  328.     makeframe(0,0,xdraw,ydraw,xsize,ysize);
  329.         pushmatrix();
  330.     (drawfunc)();
  331.     popmatrix();
  332.     savergbwindow("temp000.rgb");
  333.     sprintf(syscmd,"subimg temp000.rgb %s 0 %d 0 %d",outname,xsize-1,ysize-1);
  334.     system(syscmd);
  335.     system("rm temp000.rgb");
  336.     } else {
  337.     nx = 1+((xsize-1)/xdraw);
  338.     ny = 1+((ysize-1)/ydraw);
  339.     fno = 0;
  340.     sprintf(assemblecmd,"assemble %d %d temp1.rgb ",nx,ny);
  341.     sprintf(removecmd,"rm ");
  342.     for(y=0; y<ny; y++) {
  343.         for(x=0; x<nx; x++) {
  344.             makeframe(x,y,xdraw,ydraw,xsize,ysize);
  345.         pushmatrix();
  346.         (drawfunc)();
  347.         popmatrix();
  348.         makename(fno++,filename);
  349.         strcat(assemblecmd,filename);
  350.         strcat(assemblecmd," ");
  351.         strcat(removecmd,filename);
  352.         strcat(removecmd," ");
  353.         savergbwindow(filename);
  354.         }
  355.     }
  356.     system(assemblecmd);
  357.     system(removecmd);
  358.     sprintf(syscmd,"subimg temp1.rgb %s 0 %d 0 %d",outname,xsize-1,ysize-1);
  359.     system(syscmd);
  360.     sprintf(syscmd,"rm temp1.rgb");
  361.     system(syscmd);
  362.     }
  363.     if(orthomode)
  364.     ortho(ox1,ox2,oy1,oy2,oz1,oz2);
  365.     else
  366.     window(rl,rr,rb,rt,rnear,rfar);
  367. }
  368.  
  369. static makename(n,name)
  370. int n;
  371. char *name;
  372. {
  373.     sprintf(name,"temp%03d.rgb",n);
  374. }
  375.  
  376. static makeframe(x,y,xdraw,ydraw,xsize,ysize)
  377. int x, y;
  378. int xdraw, ydraw;
  379. int xsize, ysize;
  380. {
  381.     float l, r, b, t; 
  382.     float x1, x2, y1, y2;
  383.     float vsize, hsize;
  384.     float xrend, yrend;
  385.  
  386.     mmode(MPROJECTION);
  387.     if(orthomode) {
  388.     hsize = ox2-ox1;
  389.     vsize = oy2-oy1;
  390.     xrend = xdraw*(hsize/xsize);
  391.     yrend = ydraw*(vsize/ysize);
  392.     x1 = ox1+x*xrend;
  393.     x2 = x1+xrend;
  394.     y1 = oy1+y*yrend;
  395.     y2 = y1+yrend;
  396.     ortho(x1,x2,y1,y2,oz1,oz2);
  397.     } else {
  398.     vsize = (rt-rb);
  399.     hsize = xsize*(vsize/ysize);
  400.     xrend = xdraw*(hsize/xsize);
  401.     yrend = ydraw*(vsize/ysize);
  402.     l = x*xrend-hsize/2.0;
  403.     r = l+xrend;
  404.     b = y*yrend-vsize/2.0;
  405.     t = b+yrend;
  406.     window(l,r,b,t,rnear,rfar);
  407.     }
  408.     mmode(MVIEWING);
  409. }
  410.  
  411. /*
  412.  *    general environment drawing stuff follows 
  413.  *
  414.  *
  415.  */
  416. rendercubetoscreen(drawfunc)
  417. int (*drawfunc)();
  418. {
  419.     short x1, x2, y1, y2;
  420.     int deltax, deltay;
  421.     int xclick, yclick;
  422.     int i;
  423.  
  424.     rgb(0.0,0.0,0.0);
  425.     clear();
  426.     pushviewport();
  427.     getviewport(&x1,&x2,&y1,&y2);
  428.     deltax = x2-x1;
  429.     deltay = y2-y1;
  430.     xclick = deltax/4;
  431.     yclick = deltay/3;
  432.     mmode(MPROJECTION);
  433.     perspective(900,1.0/1.0,rnear,rfar);
  434.     mmode(MVIEWING);
  435.     if(glgetmode() & DOUBLEBUFFER)
  436.     glsetmode(INHIBITSWAP,1);
  437.     for(i=0; i<6; i++) {
  438.     pushmatrix();
  439.     switch(i) {
  440.         case 0:
  441.         setvp(1,1,x1,y1,xclick,yclick);
  442.         rot(0.0,'y');
  443.         break;
  444.         case 1:
  445.         setvp(2,1,x1,y1,xclick,yclick);
  446.         rot(90.0,'y');
  447.         break;
  448.         case 2:
  449.         setvp(3,1,x1,y1,xclick,yclick);
  450.         rot(180.0,'y');
  451.         break;
  452.         case 3:
  453.         setvp(0,1,x1,y1,xclick,yclick);
  454.         rot(270.0,'y');
  455.         break;
  456.         case 4:
  457.         setvp(1,2,x1,y1,xclick,yclick);
  458.         rot(-90.0,'x');
  459.         break;
  460.         case 5:
  461.         setvp(1,0,x1,y1,xclick,yclick);
  462.         rot(90.0,'x');
  463.         break;
  464.     }
  465.         (drawfunc)();
  466.     popmatrix();
  467.     }
  468.     if(glgetmode() & DOUBLEBUFFER) {
  469.     glsetmode(INHIBITSWAP,0);
  470.     swapbuffers();
  471.     }
  472.     popviewport();
  473. }
  474.  
  475. static setvp(xpos,ypos,xorg,yorg,xclick,yclick)
  476. int xpos,ypos,xorg,yorg,xclick,yclick;
  477. {
  478.     int x1, x2, y1, y2;
  479.  
  480.     x1 = xorg+(xpos+0)*xclick;
  481.     y1 = yorg+(ypos+0)*yclick;
  482.     x2 = xorg+(xpos+1)*xclick;
  483.     y2 = yorg+(ypos+1)*yclick;
  484.     viewport(x1,x2-1,y1,y2-1);
  485. }
  486.  
  487. rendercylinder(drawfunc,nsides)
  488. int (*drawfunc)();
  489. int nsides;
  490. {
  491.     short x1, x2, y1, y2;
  492.     float fx1, fx2, xclick;
  493.     int deltax, deltay;
  494.     int i;
  495.     float  angleper, angle, tangle;
  496.  
  497.     rgb(0.0,0.0,0.0);
  498.     clear();
  499.     pushviewport();
  500.     getviewport(&x1,&x2,&y1,&y2);
  501.     deltax = x2-x1+1;
  502.     deltay = y2-y1+1;
  503.     xclick = deltax/(float)nsides;
  504.     angleper = (2.0*M_PI)/nsides;
  505.     tangle = tan(angleper/2);
  506.     angle = 2*(180.0*atan(tangle*deltay/xclick))/M_PI;
  507.     if(glgetmode() & DOUBLEBUFFER)
  508.     glsetmode(INHIBITSWAP,1);
  509.     for(i=0; i<nsides; i++) {
  510.     fx1 = x1+i*xclick+0.5;
  511.     fx2 = x1+(i+1)*xclick+0.5;
  512.     viewport((int)fx1,((int)fx2)-1,y1,y2);
  513.     mmode(MPROJECTION);
  514.     renderfperspective(angle,(float)xclick/deltay,rnear,rfar);
  515.     rot(((i+0.5)*360.0)/nsides-90.0-45.0,'y');
  516.     mmode(MVIEWING);
  517.     pushmatrix();
  518.         (drawfunc)();
  519.     popmatrix();
  520.     }
  521.     if(glgetmode() & DOUBLEBUFFER) {
  522.     glsetmode(INHIBITSWAP,0);
  523.     swapbuffers();
  524.     }
  525.     popviewport();
  526. }
  527.  
  528. renderfacestoscreen(drawfunc)
  529. int (*drawfunc)();
  530. {
  531.     int i;
  532.     char *fixcmd;
  533.  
  534.     mmode(MPROJECTION);
  535.     perspective(900,1.0/1.0,rnear,rfar);
  536.     mmode(MVIEWING);
  537.     for(i=0; i<6; i++) {
  538.     pushmatrix();
  539.     switch(i) {
  540.         case 0:
  541.         rot(0.0,'y');
  542.         break;
  543.         case 1:
  544.         rot(90.0,'y');
  545.         break;
  546.         case 2:
  547.         rot(180.0,'y');
  548.         break;
  549.         case 3:
  550.         rot(270.0,'y');
  551.         break;
  552.         case 4:
  553.         rot(-90.0,'x');
  554.         break;
  555.         case 5:
  556.         rot(90.0,'x');
  557.         break;
  558.     }
  559.     (drawfunc)(); 
  560.     popmatrix();
  561.     }
  562. }
  563.  
  564. renderenvtofile(drawfunc,filename)
  565. int (*drawfunc)();
  566. char *filename;
  567. {
  568.     int i;
  569.     char *savename;
  570.     char *fixcmd;
  571.     char cmdbuf[256];
  572.  
  573.     mmode(MPROJECTION);
  574.     perspective(900,1.0/1.0,rnear,rfar);
  575.     mmode(MVIEWING);
  576.     for(i=0; i<6; i++) {
  577.     pushmatrix();
  578.     switch(i) {
  579.         case 0:
  580.         rot(0.0,'y');
  581.         fixcmd = "mv Et.rgb Epx.rgb";
  582.         break;
  583.         case 1:
  584.         rot(90.0,'y');
  585.         fixcmd = "iflip Et.rgb Epy.rgb 270";
  586.         break;
  587.         case 2:
  588.         rot(180.0,'y');
  589.         fixcmd = "iflip Et.rgb Emx.rgb y";
  590.         break;
  591.         case 3:
  592.         rot(270.0,'y');
  593.         fixcmd = "iflip Et.rgb Emy.rgb xy";
  594.         break;
  595.         case 4:
  596.         rot(-90.0,'x');
  597.         fixcmd = "iflip Et.rgb Epz.rgb 90";
  598.         break;
  599.         case 5:
  600.         rot(90.0,'x');
  601.         fixcmd = "iflip Et.rgb Emz.rgb xy";
  602.         break;
  603.     }
  604.     printf("before it\n");
  605.     (drawfunc)(); 
  606.     popmatrix();
  607.     savergbwindow("Et.rgb");
  608.     system(fixcmd);
  609.     printf("after it\n");
  610.     }
  611.     sprintf(cmdbuf,"assemble 3 2 %s Emx.rgb Emy.rgb Emz.rgb Epx.rgb Epy.rgb Epz.rgb",filename);
  612.     system(cmdbuf);
  613.     system("rm Et.rgb Emx.rgb Emy.rgb Emz.rgb Epx.rgb Epy.rgb Epz.rgb");
  614. }
  615.  
  616. /*
  617.  *    screen saving utilities
  618.  *
  619.  */
  620. savergbwindow(name)
  621. char *name;
  622. {
  623.     long xsize, ysize;
  624.  
  625.     if(glgetmode()&DOUBLEBUFFER) 
  626.     readsource(SRC_FRONT);
  627.     getsize(&xsize,&ysize);
  628.     savergbrect(name,0,0,xsize-1,ysize-1);
  629.     if(glgetmode()&DOUBLEBUFFER) 
  630.     readsource(SRC_BACK);
  631. }
  632.  
  633. savergbrect(name,x1,y1,x2,y2)
  634. char *name;
  635. int x1, y1, x2, y2;
  636. {
  637.     int xsize, ysize;
  638.     int y;
  639.     IMAGE *oimage;
  640.     unsigned long *lbuf, *lptr;
  641.     short *rbuf, *gbuf, *bbuf;
  642.     int togo, maxrows, thistime;
  643.  
  644.     xsize = x2-x1+1;
  645.     ysize = y2-y1+1;
  646.     maxrows = 25000/xsize;
  647.     lbuf = (unsigned long *)mymalloc(maxrows*xsize*sizeof(unsigned long));
  648.     rbuf = (short *)mymalloc(xsize*sizeof(short));
  649.     gbuf = (short *)mymalloc(xsize*sizeof(short));
  650.     bbuf = (short *)mymalloc(xsize*sizeof(short));
  651.     oimage = iopen(name,"w",RLE(1),3,xsize,ysize,3);
  652.     if(!oimage) {
  653.     fprintf(stderr,"savergbrect: can't open output file\n");
  654.     exit(1);
  655.     }
  656.     togo = ysize;
  657.     y = 0;
  658.     while(togo) {
  659.     thistime = togo;;
  660.     if(thistime>maxrows)
  661.         thistime = maxrows;
  662.         lrectread(x1+0,y1+y,x1+xsize-1,y1+y+thistime-1,lbuf);
  663.     togo -= thistime;
  664.     lptr = lbuf;
  665.     while(thistime--) {
  666.         cpacktorgb(lptr,rbuf,gbuf,bbuf,xsize);
  667.         putrow(oimage,rbuf,y,0);
  668.         putrow(oimage,gbuf,y,1);
  669.         putrow(oimage,bbuf,y,2);
  670.         lptr += xsize;
  671.         y++;
  672.     }
  673.     }
  674.     iclose(oimage);
  675.     free(lbuf);
  676.     free(rbuf);
  677.     free(gbuf);
  678.     free(bbuf);
  679. }
  680.  
  681. zoomrgbwindow(name,factor)
  682. char *name;
  683. int factor;
  684. {
  685.     long xsize, ysize;
  686.     int ixsize, iysize;
  687.     int y;
  688.     IMAGE *oimage;
  689.     unsigned long *lbuf, *lptr;
  690.     short *rbuf, *gbuf, *bbuf;
  691.     int togo, maxrows, thistime;
  692.  
  693.     if(glgetmode()&DOUBLEBUFFER) 
  694.     readsource(SRC_FRONT);
  695.  
  696.     if(factor>11) {
  697.     fprintf(stderr,"zoomrgbwindow: factor may not exceed 11\n");
  698.     exit(1);
  699.     }
  700.     getsize(&xsize,&ysize);
  701.     ixsize = xsize/factor;
  702.     iysize = ysize/factor;
  703.     xsize = ixsize*factor;
  704.     ysize = iysize*factor;
  705.     maxrows = 25000/xsize;
  706.     lbuf = (unsigned long *)mymalloc(maxrows*xsize*sizeof(unsigned long));
  707.     rbuf = (short *)mymalloc(ixsize*sizeof(short));
  708.     gbuf = (short *)mymalloc(ixsize*sizeof(short));
  709.     bbuf = (short *)mymalloc(ixsize*sizeof(short));
  710.     oimage = iopen(name,"w",RLE(1),3,ixsize,iysize,3);
  711.     if(!oimage) {
  712.     fprintf(stderr,"zoomrgbwindow: can't open output file\n");
  713.     exit(1);
  714.     }
  715.     togo = ysize;
  716.     zerorow(rbuf,ixsize);
  717.     zerorow(gbuf,ixsize);
  718.     zerorow(bbuf,ixsize);
  719.     y = 0;
  720.     while(togo) {
  721.     thistime = togo;;
  722.     if(thistime>maxrows)
  723.         thistime = maxrows;
  724.         lrectread(0,y,xsize-1,y+thistime-1,lbuf);
  725.     togo -= thistime;
  726.     lptr = lbuf;
  727.     while(thistime--) {
  728.         zoomadd(lptr,rbuf,gbuf,bbuf,factor,xsize);
  729.         lptr += xsize;
  730.         y++;
  731.         if((y%factor) == 0) {
  732.         divrow(rbuf,rbuf,factor*factor,ixsize);
  733.         divrow(gbuf,gbuf,factor*factor,ixsize);
  734.         divrow(bbuf,bbuf,factor*factor,ixsize);
  735.         putrow(oimage,rbuf,(y-1)/factor,0);
  736.         putrow(oimage,gbuf,(y-1)/factor,1);
  737.         putrow(oimage,bbuf,(y-1)/factor,2);
  738.         zerorow(rbuf,ixsize);
  739.         zerorow(gbuf,ixsize);
  740.         zerorow(bbuf,ixsize);
  741.         }
  742.     }
  743.     }
  744.     iclose(oimage);
  745.     if(glgetmode()&DOUBLEBUFFER) 
  746.     readsource(SRC_BACK);
  747.     free(lbuf);
  748.     free(rbuf);
  749.     free(gbuf);
  750.     free(bbuf);
  751. }
  752.  
  753. static zoomadd(cptr,rbuf,gbuf,bbuf,factor,n)
  754. unsigned char *cptr;
  755. short *rbuf, *gbuf, *bbuf;
  756. int factor, n;
  757. {
  758.     int f;
  759.  
  760.     f = factor;
  761.     while(n--) {
  762.     cptr++;
  763.     *bbuf += cptr[0];
  764.     *gbuf += cptr[1];
  765.     *rbuf += cptr[2];
  766.     cptr += 3;
  767.     if(--f == 0) {
  768.          f = factor;
  769.          rbuf++;
  770.          gbuf++;
  771.          bbuf++;
  772.         }
  773.     }
  774. }
  775.  
  776. /*
  777.  *    lbuftoimage -
  778.  *        do a filtered zoom on an array of longs into
  779.  *    an image file.
  780.  *
  781.  */
  782. static int gz;
  783. static IMAGE *gimage;
  784. static unsigned long *glbuf;
  785. static int gbxsize, gbysize;
  786.  
  787. static ggetimgrow(buf,y)
  788. short *buf;
  789. int y;
  790. {
  791.     unsigned long *lptr; 
  792.     int n, shift;
  793.  
  794.     lptr = glbuf+(y*gbxsize);
  795.     shift = 8*gz;
  796.     n = gbxsize;
  797.     while(n--) 
  798.      *buf++ = ((*lptr++)>>shift)&0xff;
  799. }
  800.  
  801. static gputimgrow(buf,y)
  802. short *buf;
  803. int y;
  804. {
  805.     putrow(gimage,buf,y,gz);
  806. }
  807.  
  808. lbuftoimage(lbuf,bxsize,bysize,name,ixsize,iysize,filter)
  809. unsigned long *lbuf;
  810. int bxsize, bysize;
  811. char *name;
  812. int ixsize, iysize, filter;
  813. {
  814.     gimage = iopen(name,"w",RLE(1),3,ixsize,iysize,3);
  815.     glbuf = lbuf;
  816.     gbxsize = bxsize;
  817.     gbysize = bysize;
  818.     for(gz=0; gz<3; gz++) 
  819.         filterzoom(ggetimgrow,gputimgrow,bxsize,bysize,ixsize,iysize,filter,1.0); 
  820.     iclose(gimage);
  821. }
  822.